/*
 * Copyright 2015, Google Inc. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 * * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.usoft.thrift.benchmark.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import org.HdrHistogram.Histogram;

/**
 * Utility methods to support benchmarking classes.
 */
public final class Utils {
    private static final String UNIX_DOMAIN_SOCKET_PREFIX = "unix://";

    public static final String TEST_SERVER_HOST = "foo.test.google.fr";

    // The histogram can record values between 1 microsecond and 1 min.
    public static final long HISTOGRAM_MAX_VALUE = 60000000L;
    // Value quantization will be no larger than 1/10^3 = 0.1%.
    public static final int HISTOGRAM_PRECISION = 3;

    private Utils() {
    }

    static boolean parseBoolean(String value) {
        return value.isEmpty() || Boolean.parseBoolean(value);
    }

    public static SocketAddress parseSocketAddress(String value) {
        if (value.startsWith(UNIX_DOMAIN_SOCKET_PREFIX)) {
            return null;
        } else {
            // Standard TCP/IP address.
            String[] parts = value.split(":", 2);
            if (parts.length < 2) {
                throw new IllegalArgumentException(
                    "Address must be a unix:// path or be in the form host:port. Got: "
                        + value);
            }
            String host = parts[0];
            int port = Integer.parseInt(parts[1]);
            return new InetSocketAddress(host, port);
        }
    }

    static void saveHistogram(Histogram histogram, String filename)
            throws IOException {
        File file;
        PrintStream log = null;
        try {
            file = new File(filename);
            if (file.exists() && !file.delete()) {
                System.err.println("Failed deleting previous histogram file: "
                    + file.getAbsolutePath());
            }
            log = new PrintStream(new FileOutputStream(file), false);
            histogram.outputPercentileDistribution(log, 1.0);
        } finally {
            if (log != null) {
                log.close();
            }
        }
    }

    public static int pickUnusedPort() {
        try {
            ServerSocket serverSocket = new ServerSocket(0);
            int port = serverSocket.getLocalPort();
            serverSocket.close();
            return port;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Creates a new {@link InetSocketAddress} that overrides the host with
     */
    public static InetSocketAddress testServerAddress(String host, int port) {
        try {
            InetAddress inetAddress = InetAddress.getByName(host);
            inetAddress = InetAddress.getByAddress(TEST_SERVER_HOST,
                inetAddress.getAddress());
            return new InetSocketAddress(inetAddress, port);
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
    }

}
